#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <string>
#include <sys/types.h>        
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include "log.hpp"
using namespace std;
#define MAXSLEEP 8

Log log;
void Usage(const char* string)
{
    cout << "\n\rUsage: " << string << " serverIp serverPort\n\n";  
}

int connRetry(int domain, int type, int protocol, const struct sockaddr* addr, socklen_t alen, bool &flag)
{
    int socketFd = -1;
    flag = false;
    for(int numSec = 1; numSec <= MAXSLEEP; numSec <<= 1) {
        // 重新创建套接字
        if((socketFd = socket(domain, type, protocol)) == -1) return -1;
        
        if(connect(socketFd, addr, alen) == 0) {
            // 连接成功
            flag = true;
            return socketFd;
        } 

        close(socketFd);        // 如果connect失败，关闭套接字用于下一次重连

        if(numSec <= MAXSLEEP / 2) {
            // 睡一会，等待下次重连
            printf("客户端重连服务端中, numSec: %d...\n", numSec);
            sleep(numSec);
        }
    }
    flag = false;
}

int 
main(int argc, char* argv[])
{
    if(argc != 3) {
        Usage(argv[0]);
        return -1;
    }

    // 获得服务端的IP和端口号
    string serverIp = argv[1];
    uint16_t serverPort = stoi(argv[2]);
    // 构建服务器信息
    sockaddr_in server;
    memset(&server, 0, sizeof server);
    server.sin_family = AF_INET;
    server.sin_port = htons(serverPort);
    inet_pton(AF_INET, serverIp.c_str(), &(server.sin_addr));

    while(true) {
        // 创建套接字 + connect
        bool flag = false;
        int socketFd = connRetry(AF_INET, SOCK_STREAM, 0, (sockaddr*)&server, sizeof(server), flag);
        if(flag == false) {
            cerr << "连接服务端出错!" << endl;
            break;
        }
        // printf("连接成功!\n");

        // 收发消息
        string msg;
        printf("Please enter$ ");
        getline(cin, msg);
        ssize_t n = write(socketFd, msg.c_str(), msg.size());
        if(n == -1) {
            log(WARNING, "客户端写失败, 原因: %s\n", strerror(errno));
            continue; 
        }

        char buf[1024];
        n = read(socketFd, buf, sizeof(buf) - 1);
        if(n > 0) {
            buf[n] = 0;
            printf("%s\n", buf); 
        } else if(n == 0) {
            log(WARNING, "客户端什么也没有读到!\n");
            continue;
        } else {
            log(WARNING, "客户端读取出错, 原因%s\n", strerror(errno));
            continue;
        }

        close(socketFd);
    } 
}